package keter.lab.grpc.cloud.controllers;

import com.alibaba.fastjson.JSONObject;
import com.google.common.io.ByteStreams;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import keter.lab.grpc.cloud.util.ConcurrentUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.zip.GZIPInputStream;

@RestController
@RequestMapping("/perf/http")
public class PerfHttpController {
	private static final Logger logger = LoggerFactory.getLogger(PerfHttpController.class);

	@Autowired  RestTemplate restTemplateOriginal;

	@Autowired  @Qualifier("httpClient") RestTemplate httpClientTemplate;

	@Autowired  @Qualifier("okHttp") RestTemplate okHttpTemplate;

	String server = "http://cloud-grpc-server/perf/http";

	ListeningExecutorService service = ConcurrentUtil.service(50);

	/**
	 * 基准性能：无任何远程通信
	 * @return
	 */
	@GetMapping("/basic/local")
	public String basicLocal() {
		return "hello world!";
	}

	/**
	 * RestTeplate with Default/Simple 基准测试：不推荐使用
	 * @return
	 */
	@Deprecated
	@GetMapping("/basic/simple")
	public String basicSimple() {
		return restTemplateOriginal.getForObject(server+"/basic",String.class);
	}

	/**
	 * RestTeplate with OKHttp基准远程测试
	 * @return
	 */
	@GetMapping("/basic")
	public String basic() {
		return okHttpTemplate.getForObject(server+"/basic",String.class);
	}

	/**
	 * 增加后端负载测试
	 * @param times
	 * @return
	 * @throws ExecutionException
	 * @throws InterruptedException
	 */
	@GetMapping("/basic/{times}")
	public String basic(@PathVariable int times) throws ExecutionException, InterruptedException {
		ListenableFuture[] futures = new ListenableFuture[times];
		for (int i = 0; i < times; i++) {
			futures[i] = service.submit(() -> okHttpTemplate.getForObject(server+"/basic", String.class));
		}
		List<String>  results = ConcurrentUtil.fetchResults(service,futures);
		return results.get(times-1);
	}

	/**
	 * Json对象序列化测试
	 * @return
	 */
	@GetMapping("/serialize/jsonobject")
	public String jsonSerialize() {
		JSONObject jsonObject = okHttpTemplate.getForObject(server+"/basic/jsonobject",JSONObject.class);
		return jsonObject.getString("name")+"-"+jsonObject.getString("count");
	}

	/**
	 * 大Json字符串测试
	 * @return
	 */
	@GetMapping("/bigjsonstring")
	public String bigJsonString() {
		String res =  httpClientTemplate.getForObject(server+"/bigjsonstring",String.class);
		return "success";
	}

	/**
	 * 大Json+Gzip压缩测试
	 * @return
	 * @throws IOException
	 */
	@GetMapping("/bigjsonstring/gzip")
	public String bigJsonStringGzip() throws IOException {
		HttpEntity<String> response = okHttpTemplate.exchange(server+"/bigjsonstring/gzip", HttpMethod.GET, getGzipHttpEntity(), String.class);
//		logger.info("response headers:{}",response.getHeaders());
		String res =  decompressGzip(response.getBody());
		return "success";
	}

	private HttpEntity<?> getGzipHttpEntity() {
		HttpHeaders headers = new HttpHeaders();
		headers.add(HttpHeaders.ACCEPT_ENCODING, "gzip");
		return new HttpEntity<>(null, headers);
	}

	/**
	 * 这玩意儿只支持ISO-8859-1
	 * @param str
	 * @return
	 * @throws IOException
	 */
	public static String decompressGzip(String str) throws IOException {
		ByteArrayInputStream in = new ByteArrayInputStream(str.getBytes("ISO-8859-1"));
		GZIPInputStream gzipIn = new GZIPInputStream(in);
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		ByteStreams.copy(gzipIn,out);
		return out.toString();
	}

}